package com.lucenten.collect.gnss.handler.files;

import cn.quevo.common.lang.JSONUtils;
import cn.quevo.common.lang.NumberUtils;
import cn.quevo.common.lang.StringUtils;
import com.lucenten.collect.gnss.entity.SatelliteStation;
import com.lucenten.collect.gnss.entity.TecpTecl;
import com.lucenten.collect.gnss.entity.trans.TecpTeclTrans;
import com.lucenten.collect.gnss.handler.tools.GnssContext;
import com.lucenten.collect.gnss.handler.tools.TecDateFormat;
import com.lucenten.mq.SendJmsInfo;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

import java.text.DecimalFormat;

@Data
@NoArgsConstructor
@AllArgsConstructor
public class NTools {

    private double xk,yk,tk,ik;

    public double[] before(TecpTeclTrans tecpTeclTrans, Double[] singlePath, TecpTecl tecpTecl) {
//        System.out.println("====================");
//        System.out.println(JSONUtils.format(tecpTeclTrans));
//        System.out.println(JSONUtils.format(singlePath));

        //获取周秒
        int weekSeconds = TecDateFormat.getWeekSeconds(tecpTeclTrans.getDateTime());
//        System.out.println("weekSeconds::" +weekSeconds);
        // avgAngleVelocity：平均角速度,tk：归化观测时间(t-toe)
        double avgAngleVelocity = 0, tk = 0, mk = 0, ek = 0, vk = 0, phik = 0, uk = 0, rk = 0, ik = 0, omegak = 0;
        //（1）计算卫星运行的平均角速度n
        avgAngleVelocity = Math.sqrt(GnssContext.GM / Math.pow(singlePath[10] * singlePath[10], 3));//sqrt(A)
        avgAngleVelocity = avgAngleVelocity + singlePath[5];//摄动改正项:Delta n (弧度/秒)
//        System.out.println("avgAngleVelocity::" +avgAngleVelocity);
        //（2）计算归化观测时间tk     tk=t-toe
        //其中t为电文中给出的观测时刻，toe为电文中给出的参考时刻。
        tk = weekSeconds - singlePath[11];//toe GPS周积秒
        if (tk > 302400) {
            tk = tk - 604800;
        } else if (tk < -302400) {
            tk = tk + 604800;
        }
//        System.out.println("TK:"+tk);
        //（3）计算观测时刻的卫星平近点角mk    Mk＝M0＋ntk
        //其中M0为电文中给出的参考时刻toe的平近点角。
        mk = singlePath[6] + avgAngleVelocity * tk;//M0
//        System.out.println("MK:"+mk);
        //（4）计算偏近点角Ek  Ek＝Mk＋e*sinEk
        //其中e为电文中给出的GPS轨道偏心率，Ek通过初始值Ek＝Mk，迭代两次获得
//					ek = mk;
//					ek = mk + singlePath[8] * Math.sin(ek);//e
//					ek = mk + singlePath[8] * Math.sin(ek);//e
        double ek1 = mk, ek2 = 0, error = 1e-12;
        do {
            ek2 = mk + singlePath[8] * Math.sin(ek1);
            if (Math.abs(ek2 - ek1) <= error)
                break;
            ek1 = ek2;
        } while (true);
        ek = ek1;
//        System.out.println("EK:"+ek);
        //（5）计算真近点角Vk
        vk = AzimuthElevation.getAtan(Math.cos(ek) - singlePath[8], Math.sqrt(1.0 - singlePath[8] * singlePath[8]) * Math.sin(ek));//e
//        System.out.println("VK:"+vk+";singlePath[8]:"+singlePath[8]);
        //（6）计算升交距角
        //其中ω为电文中给出的近地点角距 omega
        phik = vk + singlePath[17];//ω : omega
//        System.out.println("PHIK:"+phik);
        //（7）计算摄动改正项
        double deltau = singlePath[7] * Math.cos(2.0 * phik) + singlePath[9] * Math.sin(2.0 * phik);
        double deltar = singlePath[16] * Math.cos(2.0 * phik) + singlePath[4] * Math.sin(2.0 * phik);
        double deltai = singlePath[12] * Math.cos(2.0 * phik) + singlePath[14] * Math.sin(2.0 * phik);
//        System.out.println("修正："+deltau+":"+deltar+":"+deltai);
        //（8）计算经过摄动改正的升交距角uk、卫星矢径rk和轨道倾角ik
        uk = phik + deltau;
        rk = singlePath[10] * singlePath[10] * (1 - singlePath[8] * Math.cos(ek)) + deltar;//sqrt(A)  sqrt(A)  e
        ik = singlePath[15] + deltai + singlePath[19] * tk;
//        System.out.println("计算："+uk+":"+rk+":"+ik);
        double XK = 0, YK = 0, ZK = 0, xk = 0, yk = 0;
        //（9）计算卫星在轨道平面坐标系的坐标 xk, yk, zk
        xk = rk * Math.cos(uk);
        yk = rk * Math.sin(uk);
//        System.out.println("xk:"+xk+";yk:"+yk);
        //（10）计算观测时刻升交点经度
        omegak = singlePath[13] + (singlePath[18] - GnssContext.WO) * tk - GnssContext.WO * singlePath[11];//OMEGA   OMEGA_DOT   toeGPS周积秒
        XK = xk * Math.cos(omegak) - yk * Math.cos(ik) * Math.sin(omegak);
        YK = xk * Math.sin(omegak) + yk * Math.cos(ik) * Math.cos(omegak);
        ZK = yk * Math.sin(ik);
        this.xk = xk;
        this.tk = tk;
        this.ik = ik;
        this.yk = yk;
        tecpTeclTrans.setXk(XK);
        tecpTeclTrans.setYk(YK);
        tecpTeclTrans.setZk(ZK);

        tecpTecl.setXk(XK);
        tecpTecl.setYk(YK);
        tecpTecl.setZk(ZK);
//        System.out.println("omegak:"+omegak+";;"+XK+":"+YK+":"+ZK);
        return new double[]{XK, YK, ZK};
    }

    public void after(TecpTeclTrans tecpTeclTrans, TecpTecl tecpTecl, double[] xyz){
        /*
			先读取星历文件，然后按照公式2.3～2.13，计算出（11）中的Xk，Yk，Zk，
			在从观测文件的头文件中读取出XYZ，并转换为L B H 后,
			带入公式（2.15 2.16）就能计算出仰角和方位角了
			*/

        //（1）计算观测站在WGS-84大地坐标系下的坐标
        //L、B和H分别是观测站在大地坐标系中的经度、纬度和高程
        SatelliteStation station = tecpTeclTrans.getStation();
        double height = StringUtils.isBlank(station.getAntennaElevation()) ? 0 : station.getAntennaElevation();
        double L = station.getLongitude() * Math.PI / 180;
        double B = station.getLatitude() * Math.PI / 180;
        double H = height;
//        System.out.println("L:"+L+";B:"+B+";H:"+H);
        double a = 6378137;//地球半径
        double e2 = 0.0818;//第一偏心率
        double N = a / Math.sqrt(1.0 - e2 * e2 * Math.sin(B) * Math.sin(B));//N为该点卯酉圈曲率半径

        //（2）卫星在WGS-84坐标系下的空间直角坐标XK，YK和ZK,表示为站心地平直角坐标系中直角坐标x、y和z
        double X0 = (N + H) * Math.cos(B) * Math.cos(L);
        double Y0 = (N + H) * Math.cos(B) * Math.sin(L);
        double Z0 = (N * (1.0 - e2 * e2) + H) * Math.sin(B);
//        System.out.println("X0:"+X0+";Y0:"+Y0+";Z0:"+Z0);
        double DeltaX = xyz[0] - X0;
        double DeltaY = xyz[1] - Y0;
        double DeltaZ = xyz[2] - Z0;
//        System.out.println("DeltaX:"+DeltaX+";DeltaY:"+DeltaY+";DeltaZ:"+DeltaZ);
        double x = -Math.sin(B) * Math.cos(L) * DeltaX - Math.sin(B) * Math.sin(L) * DeltaY + Math.cos(B) * DeltaZ;
        double y = -Math.sin(L) * DeltaX + Math.cos(L) * DeltaY;
        double z = Math.cos(B) * Math.cos(L) * DeltaX + Math.cos(B) * Math.sin(L) * DeltaY + Math.sin(B) * DeltaZ;
//        System.out.println("x:"+x+";y:"+y+";z:"+z);
        //（3）计算观测站相对于卫星的距离r、仰角E0和方位角AZ
        //方位角
        double azi = AzimuthElevation.getAtan(x, y) * 180.0 / Math.PI;
        //仰角
        double ele = AzimuthElevation.getAtan(Math.sqrt(x * x + y * y), z) * 180.0 / Math.PI;
        if (ele > 90) {
            ele = ele - 360;
        }

        //保留2位小数
        azi = Double.valueOf(new DecimalFormat("0.00").format(azi));
        ele = Double.valueOf(new DecimalFormat("0.00").format(ele));

//        System.out.print("   方位角="+azi+"    仰角="+ele);
//        System.out.println("====================");
        tecpTecl.setAzimuth(azi);
        tecpTecl.setElevation(ele);
    }
}
